package com.abner.design.patterns.decorator;

/**
 * 装饰者模式
 *   定义:
 *     装饰者模式：动态的将新功能附加到对象上。在对象功能扩展方面，它比继承更有弹性，装饰者模式也体现了开闭原则(ocp)
 *   优点:
 *      装饰类和被装饰类可以独立发展，而不会相互耦合。它有效地把类的核心职责和装饰功能分开了
 *      装饰模式是继承关系的一个替代方案
 *      装饰模式可以动态地扩展一个实现类的功能
 *   缺点:
 *      多层装饰比较复杂。比如我们现在有很多层装饰，出了问题，一层一层检查，
 *      最后发现是最里层的装饰出问题了，想想工作量都害怕
 *   使用场景:
 *      需要扩展一个类的功能时
 *      需要动态地给一个对象增加功能，并可以动态地撤销时
 *      需要为一批的兄弟类进行改装或加装功能时
 *
 * 咖啡店
 * @Author: abner
 * @Date: 2022-05-03-22:25
 **/
public class CoffeeBar {

    /**
     * 星巴克咖啡订单项目（咖啡馆）：
     * 1) 咖啡种类/单品咖啡：Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
     * 2) 调料：Milk、Soy(豆浆)、Chocolate
     * 3) 要求在扩展新的咖啡种类时，具有良好的扩展性、改动方便、维护方便
     * 4) 使用 OO 的来计算不同种类咖啡的费用: 客户可以点单品咖啡，也可以单品咖啡+调料组合。
     * @param args
     */
    public static void main(String[] args) {

        // 点一份 大杯黑咖啡
        Drink longBlackCoffee = new LongBlackCoffee();
        System.out.println(longBlackCoffee.getDes() + "价格为:" + longBlackCoffee.cost());

        // +牛奶
        Drink milkDecorator = new MilkDecorator(longBlackCoffee);
        System.out.println(milkDecorator.getDes() + "价格为:" + milkDecorator.cost());

        // +巧克力
        Drink chocolateDecorator = new ChocolateDecorator(milkDecorator);
        System.out.println(chocolateDecorator.getDes() + "价格为:" + chocolateDecorator.cost());

        // +巧克力
        Drink chocolateDecoratorTwo = new ChocolateDecorator(chocolateDecorator);
        System.out.println(chocolateDecoratorTwo.getDes() + "价格为:" + chocolateDecoratorTwo.cost());

    }
}
